package org.anachronos.jeep.core.attach;

import java.io.Serializable;
import java.util.Properties;

import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.anachronos.jeep.core.agent.ProfilerRemoteControl;

public final class VirtualMachineAttachement implements Serializable {
	public enum State {
		DETACHED,
		ATTACHED,
		PROFILING
	};
	
	private State state = State.DETACHED;
	private final String id;
	private final String name;
	private final Properties systemProperties;
	
	private transient ProfilerRemoteControl profilerRemoteControl;
	private JMXServiceURL jmxServiceURL;
	
	public VirtualMachineAttachement(final String id, final String name, final Properties systemProperties) {
		this.id = id;
		this.name = name;
		this.systemProperties = systemProperties;
	}
		

	public String getId() {
		return id;
	}

	public String getName() {
		return name;
	}
	
	public State getState() {
		return state;
	}
	
	public Properties getSystemProperties() {
		return systemProperties;
	}
	
	public ProfilerRemoteControl getProfilerRemoteControl() throws Exception {
		if (profilerRemoteControl == null) {
			final JMXConnector connector = JMXConnectorFactory.connect(jmxServiceURL); 
			final MBeanServerConnection serverConnection = connector.getMBeanServerConnection();
			final ObjectName objectName = new ObjectName(ProfilerRemoteControl.NAME);
			profilerRemoteControl = 
				JMX.newMBeanProxy(serverConnection, objectName, ProfilerRemoteControl.class);
		}
		return profilerRemoteControl;
	}

	public JMXServiceURL getJmxServiceURL() {
		return jmxServiceURL;
	}

	public void setJmxServiceURL(final JMXServiceURL jmxServiceURL) {
		assert jmxServiceURL != null;
		if (!jmxServiceURL.equals(this.jmxServiceURL)) {
			this.jmxServiceURL = jmxServiceURL;
			this.profilerRemoteControl = null;
		}
	}

	public void setState(final State newState) {
		state = newState;
	}
}
